package com.azusa.ktc_user.service;

import java.util.*;
import java.util.concurrent.TimeUnit;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import com.azusa.ktc_user.entity.Follow;
import entity.Result;
import entity.StatusCode;
import org.apache.commons.lang.RandomStringUtils;
import org.springframework.amqp.rabbit.core.RabbitMessagingTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import utils.IdWorker;
import com.azusa.ktc_user.dao.UserDao;
import com.azusa.ktc_user.entity.User;
import utils.JwtUtil;

/**
 * @Description 用户 服务层
 * @author Azusa
 * @date 2020-10-12 18:33:46
*/
@Service
@Transactional
public class UserServiceImpl implements UserService{

	@Autowired
	private UserDao userDao;

	@Autowired
	private IdWorker idWorker;

	@Autowired
	private RedisTemplate redisTemplate;

	@Autowired
	private RabbitMessagingTemplate rabbitTemplate;

	@Autowired
	private BCryptPasswordEncoder encoder;

	@Autowired
	private JwtUtil jwtUtil;

	/**
	* 查询全部列表
	* @return
	*/
	public List<User> findAll() {
		return userDao.findAll();
	}

	/**
	* 条件查询+分页
	* @param whereMap
	* @param page
	* @param size
	* @return
	*/
	public Page<User> findSearch(Map whereMap, int page, int size) {
		Specification<User> specification = createSpecification(whereMap);
		PageRequest pageRequest =  PageRequest.of(page-1, size);
		return userDao.findAll(specification, pageRequest);
	}

	/**
 	* 条件查询
	* @param whereMap
	* @return
	*/
	public List<User> findSearch(Map whereMap) {
		Specification<User> specification = createSpecification(whereMap);
		return userDao.findAll(specification);
	}

	/**
	* 根据ID查询实体
	* @param id
	* @return
	*/
	public User findById(String id) {
		return userDao.findById(id).get();
	}

	/**
	* 增加
	* @param user
	*/
	public void add(User user) {
		user.setId( idWorker.nextId()+"" );
		user.setPassword(encoder.encode(user.getPassword()));
		userDao.save(user);
	}

	/**
	* 修改
	* @param user
	*/
	public void update(User user) {
		userDao.save(user);
	}

	/**
	* 删除
	* @param id
	*/
	public void deleteById(String id) {
		userDao.deleteById(id);
	}

	/**
	* 动态条件构建
	* @param searchMap
	* @return
	*/
	private Specification<User> createSpecification(Map searchMap) {

		return new Specification<User>() {

			@Override
			public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				List<Predicate> predicateList = new ArrayList<Predicate>();
				//手机号码
				if (searchMap.get("mobile")!=null && !"".equals(searchMap.get("mobile"))) {
					predicateList.add(cb.like(root.get("mobile").as(String.class), "%"+(String)searchMap.get("mobile")+"%"));
				}
				//密码
				if (searchMap.get("password")!=null && !"".equals(searchMap.get("password"))) {
					predicateList.add(cb.like(root.get("password").as(String.class), "%"+(String)searchMap.get("password")+"%"));
				}
				//昵称
				if (searchMap.get("nickname")!=null && !"".equals(searchMap.get("nickname"))) {
					predicateList.add(cb.like(root.get("nickname").as(String.class), "%"+(String)searchMap.get("nickname")+"%"));
				}
				//性别
				if (searchMap.get("sex")!=null && !"".equals(searchMap.get("sex"))) {
					predicateList.add(cb.like(root.get("sex").as(String.class), "%"+(String)searchMap.get("sex")+"%"));
				}
				//出生年月日
				if (searchMap.get("birthday")!=null && !"".equals(searchMap.get("birthday"))) {
					predicateList.add(cb.like(root.get("birthday").as(String.class), "%"+(String)searchMap.get("birthday")+"%"));
				}
				//头像
				if (searchMap.get("avatar")!=null && !"".equals(searchMap.get("avatar"))) {
					predicateList.add(cb.like(root.get("avatar").as(String.class), "%"+(String)searchMap.get("avatar")+"%"));
				}
				//E-Mail
				if (searchMap.get("email")!=null && !"".equals(searchMap.get("email"))) {
					predicateList.add(cb.like(root.get("email").as(String.class), "%"+(String)searchMap.get("email")+"%"));
				}
				//注册日期
				if (searchMap.get("regdate")!=null && !"".equals(searchMap.get("regdate"))) {
					predicateList.add(cb.like(root.get("regdate").as(String.class), "%"+(String)searchMap.get("regdate")+"%"));
				}
				//修改日期
				if (searchMap.get("updatedate")!=null && !"".equals(searchMap.get("updatedate"))) {
					predicateList.add(cb.like(root.get("updatedate").as(String.class), "%"+(String)searchMap.get("updatedate")+"%"));
				}
				//最后登陆日期
				if (searchMap.get("lastdate")!=null && !"".equals(searchMap.get("lastdate"))) {
					predicateList.add(cb.like(root.get("lastdate").as(String.class), "%"+(String)searchMap.get("lastdate")+"%"));
				}
				//在线时长（分钟）
				if (searchMap.get("online")!=null && !"".equals(searchMap.get("online"))) {
					predicateList.add(cb.like(root.get("online").as(String.class), "%"+(String)searchMap.get("online")+"%"));
				}
				//兴趣
				if (searchMap.get("interest")!=null && !"".equals(searchMap.get("interest"))) {
					predicateList.add(cb.like(root.get("interest").as(String.class), "%"+(String)searchMap.get("interest")+"%"));
				}
				//个性
				if (searchMap.get("personality")!=null && !"".equals(searchMap.get("personality"))) {
					predicateList.add(cb.like(root.get("personality").as(String.class), "%"+(String)searchMap.get("personality")+"%"));
				}
				//粉丝数
				if (searchMap.get("fanscount")!=null && !"".equals(searchMap.get("fanscount"))) {
					predicateList.add(cb.like(root.get("fanscount").as(String.class), "%"+(String)searchMap.get("fanscount")+"%"));
				}
				//关注数
				if (searchMap.get("followcount")!=null && !"".equals(searchMap.get("followcount"))) {
					predicateList.add(cb.like(root.get("followcount").as(String.class), "%"+(String)searchMap.get("followcount")+"%"));
				}

				return cb.and( predicateList.toArray(new Predicate[predicateList.size()]));
			}
		};
	}

	/**
	 * 发送手机和验证码信息给消息队列
	 * @param mobile
	 */
	@Override
	public void sendSms(String mobile){
		//随机生成4位验证码信息
		String code = new Random().nextInt(10000) + "";
		StringRedisSerializer serializer = new StringRedisSerializer();
		redisTemplate.setKeySerializer(serializer);
		redisTemplate.setValueSerializer(serializer);
		//查看是否已经存在手机与验证码信息
		if (redisTemplate.opsForValue().get("sms:" + mobile) != null){
			return;
		}
		//将手机号作为key和验证码作为value信息放入缓存中，设置失效时间为三分钟
		redisTemplate.opsForValue().set("sms:" + mobile,code, 3,TimeUnit.MINUTES);
		//发送消息给消息队列
		HashMap<String, String> params = new HashMap<>();
		params.put("mobile",mobile);
		params.put("code",code);
		rabbitTemplate.convertAndSend("sms",params);
	}

	@Override
	public Result register(String code, User user) {
		Object o = redisTemplate.opsForValue().get("sms:" + user.getMobile());
		if (o == null){
			return new Result(StatusCode.ERROR,"验证码过期");
		}
		if (!o.toString().equals(code)){
			return new Result(StatusCode.ERROR,"验证码错误");
		}
		user.setId(idWorker.nextId() + "");
		user.setPassword(encoder.encode(user.getPassword()));//加密密码
		user.setFollowcount(0);//关注数
		user.setFanscount(0);//粉丝数
		user.setOnline(0L);//在线时长
		user.setRegdate(new Date());//注册日期
		user.setUpdatedate(new Date());//更新日期
		user.setLastdate(new Date());//最后登陆日期
		userDao.save(user);
		//删除缓存
		redisTemplate.delete("sms:" + user.getMobile());
		return new Result(StatusCode.SUCCESS);
	}

	@Override
	public Result login(User user) {
		User u = userDao.findByMobile(user.getMobile());
		if (u == null){
			return new Result(StatusCode.ERROR,"手机号不存在");
		}else {
			if (!encoder.matches(user.getPassword(),u.getPassword())){
				return new Result(StatusCode.ERROR,"密码错误");
			}
		}
		String token = jwtUtil.createJWT(u.getId(), u.getNickname(), "user");
		return new Result(StatusCode.SUCCESS,token);
	}

	@Override
	@Transactional
	public void updateFons(String userId, Integer count) {
		userDao.updateFons(userId, count);
	}

	@Override
	@Transactional
	public void updateFollowCount(String userId, Integer count) {
		userDao.updateFollowCount(userId, count);
	}

}
